﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;

using Microsoft.Practices.Unity;

using Lucene.Net.Search;
using Lucene.Net.QueryParsers;
using Lucene.Net.Index;

using ERPStore.Extensions;

using ERPStore.Web.Extensions;

using CloudSoft.Extensions;

namespace ERPStore.Indexers.Lucene.Controllers
{
	public class LuceneCatalogController : ERPStore.Web.Controllers.StoreController
	{
		public LuceneCatalogController(ERPStore.Services.ICatalogService catalogService
			, ERPStore.Services.IConnectorService connectorService
			)
		{
			this.CatalogService = catalogService;
			this.ConnectorService = connectorService;
		}

		protected ERPStore.Services.ICatalogService CatalogService { get; set; }

		protected ERPStore.Services.IConnectorService ConnectorService { get; set; }

		[ERPStore.Web.Controllers.ActionFilters.AuthorizeActionFilter]
		public ActionResult Index()
		{
			var luceneService = CatalogService as Services.CatalogService;
			var content = new StringBuilder();
			content.Append("<body>");
			content.AppendFormat("Nom du service en cours : {0}<br/>", CatalogService.Name);
			if (luceneService != null)
			{
				content.AppendFormat("Nom du service sql en cours : {0}<br/>", luceneService.GetConnectorCatalogService());
			}
			content.Append("</body>");
			return Content(content.ToString(), "text/html");
		}

		//[ERPStore.Web.Controllers.ActionFilters.AuthorizeActionFilter]
		//public ActionResult Enable()
		//{
		//    ConnectorService.RegisterCatalogService();
		//    var catalogService = DependencyResolver.Current.GetService<ERPStore.Services.ICatalogService>();
		//    var analyzer = DependencyResolver.Current.GetService<global::Lucene.Net.Analysis.Analyzer>();
		//    var path = string.Format(@"{0}\FullTextCatalog", Configuration.ConfigurationSettings.AppSettings["path"]);
		//    var injectionMembers = new InjectionMember[] 
		//        { 
		//            new InjectionConstructor(path, catalogService, Logger, analyzer) ,
		//        };
		//    Logger.Debug("Change Catalog Service to FullTextCatalog with Internal {0}", catalogService.Name);

		//    var container = DependencyResolver.Current as Microsoft.Practices.Unity.IUnityContainer;
		//    container.RegisterType<ERPStore.Services.ICatalogService, Services.CatalogService>(new TransientLifetimeManager(), injectionMembers);

		//    return Content("done", "text/html");
		//}

		//[ERPStore.Web.Controllers.ActionFilters.AuthorizeActionFilter]
		//public ActionResult Disable()
		//{
		//    ConnectorService.RegisterCatalogService();
		//    var catalogService = DependencyResolver.Current.GetService<ERPStore.Services.ICatalogService>();
		//    Logger.Debug("Change Catalog Service to {0}", catalogService.Name);
		//    return Content("done", "text/html");
		//}

		//[ERPStore.Web.Controllers.ActionFilters.AuthorizeActionFilter]
		//public ActionResult Reindex()
		//{
		//    EventPublisherService.Publish(new ERPStore.Events.GlobalEvent()
		//    {
		//        EventName = "reindexationneeded",
		//    });

		//    var content = new StringBuilder();
		//    content.Append("<body>");
		//    content.AppendFormat("Réindexation demandée", CatalogService.Name);
		//    content.Append("</body>");
		//    return Content(content.ToString(), "text/html");
		//}

		[ERPStore.Web.Controllers.ActionFilters.AuthorizeActionFilter]
		public ActionResult Query(string search, string query)
		{
			var output = new StringBuilder();

			output.Append("<html>");
			output.Append("<body>");

			output.Append("<h1>Lucene</h1>");
			output.Append("<h2>Search</h2>");
			output.Append("<form method=get>");
			output.AppendFormat("<textarea name=search id=search cols=80 rows=5>{0}</textarea>", search ?? Request["search"]);
			output.Append("<input type=submit value=go />");
			output.Append("</form>");

			var luceneService = GlobalConfiguration.Configuration.DependencyResolver.GetService<ERPStore.Services.ICatalogService>() as Services.CatalogService;

			if (luceneService == null
				|| luceneService.Name != "Lucene")
			{
				output.Append("<p>lucene service not activated</p>");
				output.Append("</body>");
				output.Append("</html>");
				return Content(output.ToString(), "text/html");
			}

			Query q = null;
			Sort sort = null;
			if (query.IsNullOrTrimmedEmpty())
			{
				var filter = luceneService.CreateProductListFilter(HttpContext.GetWebContextParameterList());
				filter.Search = search;
				q = luceneService.CreateQueryByProductListFilter(filter, global::Lucene.Net.QueryParsers.QueryParser.Operator.OR);
				sort = luceneService.CreateSort(filter.SortList);
			}
			else
			{
				q = new TermQuery(new Term(query));
			}

			var count = 0;
			var page = 0;
			var pageSize = 100;
			if (q == null)
			{
				return View();
			}

			var directoryInfo = new System.IO.DirectoryInfo(luceneService.IndexPath);
			var lockFactory = new global::Lucene.Net.Store.NoLockFactory();
			var directory = global::Lucene.Net.Store.FSDirectory.Open(directoryInfo, lockFactory);

			IndexSearcher searcher = null;

			searcher = new IndexSearcher(directory, true);
			var numHits = Math.Min((page + 1) * pageSize, searcher.MaxDoc());
			// var collector = TopScoreDocCollector.create(numHits, true);
			var collector = TopFieldCollector.create(sort, numHits, true, true, true, false);
			// var weight = q.CreateWeight(searcher);
			// var score = weight.Scorer(searcher.GetIndexReader(), true, true);
			// collector.SetScorer(score);

			searcher.Search(q, collector);

			count = collector.GetTotalHits();

			var docs = collector.TopDocs().ScoreDocs.OrderByDescending(i => i.score);

			output.Append("<h2>Query</h2>");

			output.Append("<form method=post>");
			output.AppendFormat("<textarea name=query id=query cols=80 rows=5>{0}</textarea>", q.ToString());
			output.Append("<input type=submit value=go />");
			output.Append("</form>");

			output.Append("<h2>Sort</h2>");
			output.AppendFormat("<p>{0}</p>", System.Web.HttpUtility.HtmlEncode(sort.ToString()));

			output.AppendFormat("<p>Found {0} results</p>", count);
			output.Append("<table border=1 cellspacing=0 cellpadding=0>");

			var indexedField = new Dictionary<string, float>() {
				    { "Title", 10f },
				    { "Code" , 8f},
				    { "Keywords", 6f},
				    { "ShortDescription", 4f},
				    { "LongDescription", 4f},
				    { "StrengthsPoints", 4f},
					{ "GTIN.EAN", 2f},
					{ "GTIN.UPC", 2f},
					 };

			output.Append("<tr>");
			output.Append("<td>Score</td>");
			output.Append("<td>DocId</td>");

			foreach (var key in indexedField.Keys)
			{
				output.AppendFormat("<td>{0}</td>", key);
			}

			var words = search.ToWordList();
			output.Append("</tr>");
			foreach (var doc in docs)
			{
				var searchDoc = searcher.Doc(doc.doc);
				output.Append("<tr>");
				output.AppendFormat("<td>{0:F4}</td>", doc.score);
				output.AppendFormat("<td>{0}</td>", doc.doc);
				foreach (var key in indexedField.Keys)
				{
					var field = searchDoc.GetField(key);
					if (field != null)
					{
						string value = field.StringValue();
						foreach (var word in words)
						{
							var position = value.IndexOf(word, StringComparison.InvariantCultureIgnoreCase);
							if (position != -1)
							{
								value = value.Substring(0, position) + string.Format("<span style='background-color:yellow'>" + value.Substring(position, word.Length) + "</span>") + value.Substring(position + word.Length);
							}
						}

						output.AppendFormat("<td>{0}</td>", value);
					}
					else
					{
						output.AppendFormat("<td>{0}</td>", key);
					}
				}
				output.Append("</tr>");
			}

			output.Append("</table>");
			output.Append("</body>");
			output.Append("</html>");

			if (searcher != null)
			{
				searcher.Close();
			}

			if (directory != null)
			{
				directory.Close();
			}

			return Content(output.ToString(), "text/html");
		}

	}
}
